﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using System.Xml.Serialization;
using System.Xml;
using System.IO;

namespace AntikCompta.Data
{
    public delegate void ExerciceChangedHandler(object sender);

    internal class DataMng
    {
        private String mPath;
        private Hashtable mExercices;
        private String mDir = "donnees";
        private String mPref = "Exercice_";

        public event ExerciceChangedHandler ExerciceChanged;

        internal DataMng()
        {
            mExercices = new Hashtable();
        }

        internal String Fichier
        {
            get { return mPath; }
        }

        internal ICollection ExerciceListe
        {
            get { return mExercices.Values; }
        }

        internal Journal Journal
        {
            get { return new Journal(mExercices); }
        }

        internal bool AjouterExercice(Exercice aExercice)
        {
            if (aExercice == null)
                return false;

            if (mExercices.ContainsKey(aExercice.Annee) == true)
                return false;

            mExercices[aExercice.Annee] = aExercice;

            if (ExerciceChanged != null)
                ExerciceChanged(this);

            return true;
        }

        internal bool GetExercice(int aAnnee, out Exercice aExercice)
        {
            aExercice = null;
            if(mExercices.Count<=0)
                return false;

            if (mExercices.ContainsKey(aAnnee) == false)
                return false;

            aExercice = (Exercice)mExercices[aAnnee];

            return true;
        }

        internal bool Charger(String aPath)
        {
            mExercices.Clear();

            if ((aPath == null) || (aPath.Length <= 0))
                return false;

            if (File.Exists(aPath) == false)
                return false;

            mPath = aPath;
            XmlSerializer s = new XmlSerializer(typeof(List<String>));
            StreamReader a = new StreamReader(aPath);
            List<String> fileListe = (List<String>)s.Deserialize(a);
            a.Close();

            String path = Path.GetDirectoryName(aPath);

            foreach (String str in fileListe)
            {
                Exercice ex;
                if (Charger(Path.Combine(path, str), out ex) == true)
                    AjouterExercice(ex);
            }

            return true;
        }

        private bool Charger(String aPath, out Exercice aExercice)
        {
            aExercice = null;
            XmlSerializer s = new XmlSerializer(typeof(Exercice));
            StreamReader a = new StreamReader(aPath);
            aExercice = (Exercice)s.Deserialize(a);
            a.Close();

            return true;
        }

        internal bool Sauver(String aFile)
        {
            mPath = aFile;
            String dir = Path.GetDirectoryName(aFile);

            List<String> fileListe = new List<string>();
            foreach (Exercice ex in mExercices.Values)
            {
                Sauver(dir, ex.Annee, ref fileListe);
            }

            XmlSerializer s = new XmlSerializer(typeof(List<String>));
            StreamWriter a = new StreamWriter(mPath);
            s.Serialize(a, fileListe);
            a.Close();

            return true;
        }

        private bool Sauver(String aRootDir, int aAnnee, ref List<String> aFileListe)
        {
            Exercice exercice;
            if (GetExercice(aAnnee, out exercice) == false)
                return false;

            String dir = Path.Combine(aRootDir, mDir);
            if (Directory.Exists(dir) == false)
                Directory.CreateDirectory(dir);

            String path = Path.Combine(dir, mPref);
            path+=aAnnee+".xml";

            // Use the constructor that takes a type and XmlRootAttribute.
            XmlSerializer s = new XmlSerializer(typeof(Exercice));
            StreamWriter a = new StreamWriter(path);
            s.Serialize(a, exercice);
            a.Close();

            path = Path.Combine(mDir, mPref);
            path += aAnnee + ".xml";

            aFileListe.Add(path);

            return true;
        }

        internal bool GetBilan(int aAnnee, out List<Produit> aListe)
        {
            aListe = new List<Produit>();
            foreach (Exercice ex in mExercices.Values)
            {
                if (ex.Annee <= aAnnee)
                {
                    ex.GetBilan(aAnnee, ref aListe);
                }
            }
            return true;
        }

        internal float GetBenefice(int aAnnee)
        {
            List<Produit> liste;
            if (GetBilan(aAnnee, out liste) == false)
                return 0;

            float benefice = 0;
            foreach (Produit p in liste)
            {
                benefice += p.CalculBenefice(aAnnee);
            }
            return benefice;
        }

        internal float GetAchats(int aAnnee)
        {
            List<Produit> liste;
            if (GetBilan(aAnnee, out liste) == false)
                return 0;

            float tot_achats = 0;
            foreach (Produit p in liste)
            {
                if (p.DateAchat.Year == aAnnee)
                {
                    tot_achats += p.Vendeur.GetPrixAchat(p.PrixAchat);
                }
            }

            return tot_achats;
        }

        internal float GetVentes(int aAnnee)
        {
            List<Produit> liste;
            if (GetBilan(aAnnee, out liste) == false)
                return 0;

            float tot_ventes = 0;
            foreach (Produit p in liste)
            {
                tot_ventes += p.CalculPrixVente(aAnnee);
            }

            return tot_ventes;
        }

        internal float GetValeurStockFinal(int aAnnee)
        {
            float valStock = 0;
            foreach (Exercice ex in mExercices.Values)
            {
                if (ex.Annee <= aAnnee)
                {
                    IEnumerable<Produit> liste = ex.GetNonVendus(aAnnee);
                    foreach (Produit p in liste)
                    {
                        valStock += p.Vendeur.GetPrixAchat(p.PrixAchat);
                    }
                }
            }
            return valStock;
        }

        internal float GetResteCaisse(ref Stock aStock, DateTime aDate)
        {
            float somme = 0;
            foreach (Exercice ex in mExercices.Values)
            {
                if (ex.Annee < aDate.Year)
                    somme += ex.GetResteCaisse(ref aStock, 12);
                else if (ex.Annee == aDate.Year)
                    somme += ex.GetResteCaisse(ref aStock, aDate.Month);
            }
            return somme;
        }
    }
}
